package gu.simplemq;

import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.EnumMap;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import com.google.common.net.HostAndPort;

/**
 * activemq连接参数配置对象
 * @author guyadong
 *
 */
public abstract class MQProperties extends Properties{
	private static final long serialVersionUID = 1L;
	private final MQPropertiesHelper helper = getPropertiesHelper();
	private final MQConstProvider constProvider = helper.getConstProvider();
	public MQProperties() {
		super();
	}
	public MQProperties(Properties defaults) {
		super(defaults);
	}
	public abstract MQPropertiesHelper getPropertiesHelper();
	/**
	 *  对参数(props)中的服务地址归一化<br>
	 * @return always props,确保{@code ACON_BROKER_URL}有定义
	 */
	public MQProperties normalizeLocation(){
		return helper.normalizeLocation(this);
	}
	public String getLocationAsString(){
		return helper.getLocationAsString(this);
	}
	public URI getLocation(){
		return helper.getLocation(this);
	}
	public HostAndPort getHostAndPort(){
		return helper.getHostAndPort(this);
	}
	/**
	 * 初始化 uri 
	 * @param uri 不可为{@code null}
	 */
	public MQProperties initURI(URI uri) {
		setProperty(constProvider.getMainLocationName(),checkNotNull(uri,"uri is null").toString());
		return this;
	}
	/**
	 * 初始化 uri 
	 * @param uri 不可为{@code null}
	 */
	public MQProperties initURI(String uri) {
		setProperty(constProvider.getMainLocationName(),checkNotNull(uri,"uri is null"));
		return this;
	}
	
	/**
	 * 使用 map 定义的参数作为初始化当前对象<br>
	 * 过滤掉 map 中 Key 为 {@code null} 或 Value 为 {@code null} 值<br>
	 * @param map 参数,为{@code null} 忽略
	 * @return 当前对象
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public MQProperties init(Map map){
		clear();
		if (map instanceof Properties) {
			Properties props = (Properties) map;
			for (Enumeration<?> itor = props.propertyNames(); itor.hasMoreElements();) {
				String key = (String) itor.nextElement();
				put(key, props.get(key));
			}
		} else if (null != map) {
			for (Map.Entry e : (Set<Map.Entry>) map.entrySet()) {
				if (null != e.getKey() && null != e.getValue()) {
					put(e.getKey(), e.getValue());
				}
			}
		}
		return this;
	}
	public MQProperties with(MQLocationType type) {
		helper.with(type);
		return this;
	}

	public <E extends Enum<E>> EnumMap<E, Object> asEnumMap(
			Class<E> keyType, 
			boolean removeIfSet, 
			String strippedPrefix){
		return helper.asEnumMap(keyType, this, removeIfSet, strippedPrefix);
	}
	public <E extends Enum<E>> EnumMap<E, Object> asEnumMap(
			Class<E> keyType){
		return asEnumMap(keyType, false, null);
	}
}
